package com.easy.core.tools;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.easy.core.exception.UnableCloseException;

/**
 * <p>Description: 通用工具类</p>
 * <p>CreateDate:@2013-8-22</p>
 * @author zhangj
 */
public class Common {
	
	private static Logger log = Logger.getLogger(Common.class);
	
	/**
	 * 描述：通用关闭方法，主要是实现Closeable的IO类、JDBC相关类的关闭操作，支持多参数。
	 * 		e.g.
	 * 			Common.close(fileInputStream, rs, stmt, conn);
	 * @method cloas	将要关闭的对象数组
	 * @param objects
	 */
	public static void close(Object... objects){
		close(log, objects);
	}
	
	/**
	 * 描述：通用关闭方法，主要是实现Closeable的IO类、JDBC相关类的关闭操作，支持多参数。
	 * 		e.g.
	 * 			Common.close(Logger.getLogger(Common.class), rs, stmt, conn);
	 * @method close	
	 * @param log		日志
	 * @param objects	将要关闭的对象数组
	 */
	public static void close(Logger log, Object... objects){
		if(null==objects)return;
		int i = 0;
		for(Object obj : objects){
			try {
				if(null==obj)continue;
				if(obj instanceof Closeable){
					if(obj instanceof Flushable) ((Flushable) obj).flush();
					((Closeable) obj).close();
				}else if(obj instanceof Connection){
					Connection temp = (Connection) obj;
					temp.setAutoCommit(true);
					temp.close();
				}else if(obj instanceof Statement){
					((Statement) obj).close();
				//PreparedStatement集成Statement，所以可以省略
				}else if(obj instanceof ResultSet){
					((ResultSet) obj).close();
				}else if(obj instanceof SessionFactory){
					((SessionFactory) obj).close();
				}else if(obj instanceof Session){
					((Session) obj).close();
				}else throw new UnableCloseException("Don't know how to close objects["+i+"].");
				i++;
			} catch (IOException e){
				log.error(e);
			} catch (SQLException e) {
				log.error(e);
			}
		}
	}
	
	public static void close(Closeable... closeables){
		close(log, closeables);
	}
	
	public static void close(Logger log, Closeable... closeables){
		if(null==closeables) return;
		for(Closeable obj : closeables){
			try {
				if(null==obj)continue;
				obj.close();
			} catch (IOException e) {
				log.error(e);
			}
		}
	}
	
	public static void close(Connection... connections){
		close(log, connections);
	}
	
	public static void close(Logger log, Connection... connections){
		if(null==connections) return;
		for(Connection obj : connections){
			try {
				if(null==obj)continue;
				obj.close();
			} catch (SQLException e) {
				log.error(e);
			}
		}
	}
	
	public static void close(Statement... statements){
		close(log, statements);
	}
	
	public static void close(Logger log, Statement... statements){
		if(null==statements) return;
		for(Statement obj : statements){
			try {
				if(null==obj)continue;
				obj.close();
			} catch (SQLException e) {
				log.error(e);
			}
		}
	}
	
	public static void close(ResultSet... resultSets){
		close(log, resultSets);
	}
	
	public static void close(Logger log, ResultSet... resultSets){
		if(null==resultSets) return;
		for(ResultSet obj : resultSets){
			try {
				if(null==obj)continue;
				obj.close();
			} catch (SQLException e) {
				log.error(e);
			}
		}
	}
	
	/**
	 * 描述：迭代集合
	 * @method iterate
	 * @param array
	 * @param handle
	 */
//	public static <T> JsonArray iterate(Collection<T> array,IterateHandle<T> handle) throws JSONException{
//		return iterate(array, handle, false);
//	}
	
	/**
	 * 描述：迭代集合
	 * @method iterate
	 * @param array
	 * @param handle
	 * @param ignoreNull	是否忽略null，如果为true，当数据为null时就跳过循环，否则存储null值
	 * @return
	 * @throws JSONException JsonArray
	 */
//	public static <T> JsonArray iterate(Collection<T> array,IterateHandle<T> handle, boolean ignoreNull) throws JSONException{
//		JsonArray temp = new JsonArray();
//		for(T obj : array){
//			JSONObject json = handle.exec(obj, handle);
//			if(ignoreNull && json == null) continue;
//			temp.put(json);
//		}
//		return temp;
//	}
	
	private static final int BUFFER_SIZE=16*1024;
	/**
	 * 描述：文件复制
	 * @method copy
	 * @param src	源文件
	 * @param dst	新文件
	 * @return boolean
	 */
	public static boolean copy(File src, File dst) {
		boolean result=false;  
		InputStream in = null;  
		OutputStream out = null;  
		try {  
			in = new BufferedInputStream(new FileInputStream(src), BUFFER_SIZE);  
			out = new BufferedOutputStream(new FileOutputStream(dst), BUFFER_SIZE);  
			byte[] buffer = new byte[BUFFER_SIZE];  
			int len = 0;  
			while ((len = in.read(buffer)) > 0) {  
				out.write(buffer, 0, len);  
			}
			result=true;  
		} catch (Exception e) {
			log.error(e);
			result=false;  
		} finally {
			Common.close(in, out);
		}
		return result;  
    }
	
	/**
	 * 描述：html特殊字符转义
	 * @method htmlSpecialChars
	 * @param temp
	 * @return String
	 */
	public static String htmlSpecialChars(String temp){
		if(null == temp) return temp;
		temp = temp.replace("&", "&amp;");
		temp = temp.replace("\"", "&quot;");
		temp = temp.replace("<", "&lt;");
		temp = temp.replace(">", "&gt;");
		return temp;
	}
	
	/**
	 * 描述：引号等特殊字符转义为“\”开头的字符串
	 * @method quotSpecialChars
	 * @param temp
	 * @return String
	 */
	public static String escapeJavaScript(String temp){
		return StringEscapeUtils.escapeJavaScript(temp);
	}
	
	/**
     * <p>检查字符串是否是整数或小数。</p>
     * <pre>
     * Common.isNumeric(null)    = false
     * Common.isNumeric("")      = false
     * Common.isNumeric("  ")    = false
     * Common.isNumeric("123")   = true
     * Common.isNumeric("-123")  = true
     * Common.isNumeric("12 3")  = false
     * Common.isNumeric("ab2c")  = false
     * Common.isNumeric("12-3")  = false
     * Common.isNumeric("12.3")  = true
     * Common.isNumeric("-12.3") = true
     * </pre>
     * @param str	待检测的字符串，可能为null
     * @return <code>true</code> 如果只包含整数或小数且不为null
     */
//	public static boolean isNumeric(String str){
//		if(null == str) return false;
//		return str.trim().matches(RegexString.DOUBLE_MATCHES);
//	}
	
	/**
	 * 描述：首字母大写，以空白字符间隔判断词语
	 * @param str		原字符串
	 * @return String	转换后的字符串
	 */
	public static String capitalize(String str){
		return WordUtils.capitalize(str);
	}
	
	/**
	 * 描述：首字母大写，按照设定的间隔符判断词语
	 * @param str		   原字符串
	 * @param delimiters 间隔符
	 * @return String	  转换后的字符串
	 */
	public static String capitalize(String str, char[] delimiters){
		return WordUtils.capitalize(str, delimiters);
	}
	
	/**
	 * 描述：添加前缀且原字符串首字母大写
	 * @param org		原字符串
	 * @param prefix	前缀字符串
	 * @return String
	 */
	public static String addPrefix(String org, String prefix){
		return addPrefix(org, prefix, true);
	}
	
	/**
	 * 描述：添加前缀
	 * @param org			原字符串
	 * @param prefix		前缀字符串
	 * @param isCapitalize	原字符串是否首字母大写
	 * @return String
	 */
	public static String addPrefix(String org, String prefix, boolean isCapitalize){
		return StringUtils.isNotBlank(org)&&StringUtils.isNotBlank(prefix)&&!org.startsWith(prefix)?
				(prefix+(isCapitalize?capitalize(org):org)):org;
	}
	
	/**
	 * 描述：添加后缀
	 * @param org		原字符串
	 * @param suffix	后缀字符串
	 * @return String
	 */
	public static String addSuffix(String org, String suffix){
		return StringUtils.isNotBlank(org)&&StringUtils.isNotBlank(suffix)&&!org.endsWith(suffix)?(org+suffix):org;
	}
	
	/**
	 * 描述：添加间隔符+后缀字符串，且排除重复
	 * @param str				原字符串
	 * @param addStr			后缀字符串
	 * @param separatorChars	间隔符
	 * @return String
	 */
	public static String addNotExistCharacter(String str, String addStr, String separatorChars){
		if(null == separatorChars) separatorChars = "";
		if(StringUtils.contains(separatorChars+str+separatorChars, addSuffix(addPrefix(addStr, separatorChars, false), separatorChars)))
			return str;
		return StringUtils.isNotBlank(str)?(str+(StringUtils.isNotBlank(addStr)?(separatorChars+addStr):"")):addStr;
	}
	
	/**
	 * 描述：获取密码的安全强度
	 * @param pass		密码
	 * @return Integer	安全强度
	 */
//	public static Integer getPassIntensity(String pass){
//		if(StringUtils.isBlank(pass)) return -2;//非常不安全
//		if(pass.matches(GlobalConst.PASS_INTENSITY[2])) return 2;
//		if(pass.matches(GlobalConst.PASS_INTENSITY[1])) return 1;
//		if(pass.matches(GlobalConst.PASS_INTENSITY[0])) return 0;
//		return -1;//未知安全强度
//	}
	
	
}
